/*
 * Copyright 2009-2010 Belmont Software Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.belmont.backup.server;

import com.belmont.backup.*;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import javax.servlet.*;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
import javax.servlet.http.*;
import org.json.*;
import com.belmont.backup.client.BackupAdminInterface;

public class BackupUIServlet extends RemoteServiceServlet implements BackupAdminInterface, IBackupConstants {
    Config serviceConfig;

    public String getVersion() {
        return "2.0";
    }

    public String getBackupRoot() {
        return BackupService.getInstance().getBackupDirectory();
    }

    public String setBackupRoot(String root) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setBackupRoot(root);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
        File f = new File(root);
        if (f.exists()) {
            return "Backup root changed to "+f.getAbsolutePath();
        } else {
            return "Backup root changed to "+f.getAbsolutePath() +" [warning non-existent directory]";
        }
    }

    public String[] getBrandingStrings() {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();
        String ar[] = new String[BRANDING_LENGTH];
        if (c.getCompany() != null) {
            ar[BRANDING_COMPANY] = c.getCompany();
        } else {
            ar[BRANDING_COMPANY] = "Belmont";
        }
        if (c.getProduct() != null) {
            ar[BRANDING_PRODUCT] = c.getProduct();
        } else {
            ar[BRANDING_PRODUCT] = "Backup Service";
        }
        if (c.getLogoURL() != null) {
            ar[BRANDING_LOGO_URL] = c.getLogoURL();
        } else {
            ar[BRANDING_LOGO_URL] = "/ui/Belmont.png";
        }
        if (c.getClientName() != null) {
            ar[BRANDING_CLIENT_NAME] = c.getClientName();
        } else {
            ar[BRANDING_CLIENT_NAME] = "Backup Service";
        }
        if (c.getCompanyURL() != null) {
            ar[BRANDING_COMPANY_URL] = c.getCompanyURL();
        } else {
            ar[BRANDING_COMPANY_URL] = "http://www.belmont-ss.com";
        }

        return ar;
    }

    public void setBrandingStrings(String s[]) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        if (s[BRANDING_COMPANY] != null) {
            c.setCompany(s[BRANDING_COMPANY]);
        }
        if (s[BRANDING_PRODUCT] != null) {
            c.setProduct(s[BRANDING_PRODUCT]);
        }
        if (s[BRANDING_LOGO_URL] != null) {
            c.setLogoURL(s[BRANDING_LOGO_URL]);
        }
        if (s[BRANDING_CLIENT_NAME] != null) {
            c.setClientName(s[BRANDING_CLIENT_NAME]);
        }
        if (s[BRANDING_COMPANY_URL] != null) {
            c.setCompanyURL(s[BRANDING_COMPANY_URL]);
        }
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getBackups() {
        try {
            JSONArray ar = new JSONArray();
            Vector<String[]> clients = BackupService.getInstance().getClients();
            Enumeration<String[]> cl = clients.elements();
            while (cl.hasMoreElements()) {
                String client[] = cl.nextElement();
                JSONObject h = new JSONObject();
                h.put("uuid", client[0]);
                h.put("host", client[1]);
                h.put("userid", client[2]);
                JSONObject v =  BackupService.getInstance().getServer().getAvailableVersions(client[0]);
                if (v != null) {
                    h.put("backups", v);
                }
                ar.put(h);
            }

            return ar.toString();
        } catch (Exception ex) {
            Utils.log(LOG_ERROR, "Error in getBackups", ex);
            return null;
        }
    }

    /**
     * Delete the given backups. Each element in the vector is of the following form:
     *
     *  <uuid>/* -- deletes all backups for this uuid
     *  <uuid>/%<path> -- deletes all backups for this uuid and the given path
     *  <uuid>/<backupid> -- deletes the given backupid for the given uuid
     */
    public int deleteBackups(Vector<String> backups) {
        if (backups == null) {
            return 0;
        }
        int counter = 0;
        Enumeration<String> bc = backups.elements();
        while (bc.hasMoreElements()) {
            String backup = bc.nextElement();
            int idx = backup.indexOf('/');

            if (idx == -1) {
                Utils.log(LOG_ERROR, "Bad backup spec for delete: "+backup);
                continue;
            }
            try {
                String uuid = backup.substring(0, idx);
                backup = backup.substring(idx+1);
                FileBackupServer fserver = BackupService.getInstance().fserver;
                if (backup.charAt(0) == '*') {
                    // delete all backups for this uuid
                    Utils.log(LOG_INFO, "Deleting all backups for session "+uuid);
                    fserver.deleteAllBackups(uuid);
                    counter++;
                    Utils.log(LOG_INFO, "Deleted all backups for session "+uuid);
                } else if (backup.charAt(0) == '%') {
                    // delete all backups for the given path
                    backup = backup.substring(1);
                    Utils.log(LOG_INFO, "Deleting all backups for path "+backup+" and session "+uuid);
                    fserver.deleteBackupsForPath(uuid, backup);
                    counter++;
                    Utils.log(LOG_INFO, "Deleted all backups for path "+backup+" and session "+uuid);
                } else {
                    // delete this specific backup
                    Utils.log(LOG_INFO, "Deleting backup "+backup);
                    fserver.deleteBackup(uuid, backup);
                    counter++;
                    Utils.log(LOG_INFO, "Deleted backup "+backup);
                }
            } catch (Exception ex) {
                Utils.log(LOG_ERROR, "Error deleting backup", ex);
            }
        }

        return counter;
    }

    public String getLogDirectory() {
        return BackupService.getInstance().getLogDirectory().getAbsolutePath();
    }

    public boolean isServiceEnabled() {
        Config c = BackupService.getInstance().getConfig();

        return c.isServiceEnabled();
    }

    public void setEnableService(boolean value) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setServiceEnabled(value);
        try {
            svc.saveConfig();
            if (value) {
                Utils.log(LOG_INFO, "Service enabled");
            } else {
                Utils.log(LOG_INFO, "Service disabled");
            }
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getServiceHost() {
        return BackupService.getInstance().getServiceHost();
    }

    public Vector<String[]> getClients() {
        try {
            return BackupService.getInstance().getClients();
        } catch (Exception ex) {
            Utils.log(LOG_ERROR, "Exception in getClients", ex);
            return null;
        }
    }

    public String[] getIncludeFilters() {
        Config c = BackupService.getInstance().getConfig();

        return c.getDefaultIncludeFilter();
    }


    public void setIncludeFilters(String filters[]) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setIncludeFilters(filters);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String[] getExcludeFilters() {
        Config c = BackupService.getInstance().getConfig();

        return c.getDefaultExcludeFilter();
    }

    public void setExcludeFilters(String filters[]) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setExcludeFilters(filters);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getSchedule() {
        Config c = BackupService.getInstance().getConfig();

        return c.getBackupSchedule();
    }

    public void setSchedule(String schedule) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();
        c.setBackupSchedule(schedule);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getConfigSchedule() {
        Config c = BackupService.getInstance().getConfig();

        return c.getConfigSchedule();
    }

    public void setConfigSchedule(String schedule) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();
        c.setConfigSchedule(schedule);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public int getMaxVersions() {
        Config c = BackupService.getInstance().getConfig();

        return c.getMaxVersions();
    }

    public void setMaxVersions(int max) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setMaxVersions(max);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String restart(int seconds) {
        return BackupService.getInstance().restart(seconds);
    }

    public void setPort(int port) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setPort(port);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }
    
    public String[] getBackupDirectories() {
        Config c = BackupService.getInstance().getConfig();

        return c.getBackupDirectories();
    }

    public void setBackupDirectories(String list[]) {
        try {
            BackupService svc = BackupService.getInstance();
            Config c = svc.getConfig();


            c.setBackupDirectories(list);
            try {
                svc.saveConfig();
            } catch (IOException ex) {
                Utils.log(LOG_ERROR, "Error saving configuration", ex);
            }
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
    }

    public String[] getAdminUser() {
        return BackupService.getInstance().getAdminUser();
    }

    public void setAdminUser(String userpass[]) {
        BackupService.getInstance().setAdminUser(userpass);
    }

    public boolean getAllowBackupDirChange() {
        Config c = BackupService.getInstance().getConfig();

        return c.getAllowBackupDirChange();
    }

    public void setAllowBackupDirChange(boolean value) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setAllowBackupDirChange(value);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getRestoreDirectory() {
        Config c = BackupService.getInstance().getConfig();

        return c.getRestoreDirectory();
    }

    public void setRestoreDirectory(String dir) {
        BackupService svc = BackupService.getInstance();
        Config c = svc.getConfig();

        c.setRestoreDirectory(dir);
        try {
            svc.saveConfig();
        } catch (IOException ex) {
            Utils.log(LOG_ERROR, "Error saving configuration", ex);
        }
    }

    public String getServiceIP() {
        return BackupService.getInstance().getServiceIP();
    }

    public String getServicePort() {
        return BackupService.getInstance().getServicePort();
    }

    public String getStartedOn() {
        return BackupService.getInstance().getStartedOn();
    }

    public BackupUIServlet() {
    }
}
